#include "StdAfx.h"
#include "WebPageManager.h"
#include "WebPage.h"
#include <atlbase.h>
#include <atlwin.h>
#include <atlcom.h>
#include <ocidl.h>
#include <mshtml.h>
#include <mshtmdid.h>
#include <exdisp.h>
#include <exdispid.h>
#include <atltypes.h>

CComModule _Module;
int CWebPageManager::sm_webpageId = 1;
const LPCTSTR HOST_PAGE_CLASS = _T("PagesHostWindow");
// www.25925.com, rubbish


CWebPageManager::CWebPageManager(void)
{
	m_hWndMain = NULL;
	m_hWndWebPageParent = NULL;
	m_pTabs = NULL;
}

CWebPageManager::~CWebPageManager(void)
{
}

bool CWebPageManager::Init(HWND hWndMain)	// init com and "atlaxwin80"
{
	if ( hWndMain == NULL )
		return false;

	if ( m_hWndMain != NULL )
		return false;

	HRESULT hr = OleInitialize(0);
	if ( FAILED(hr) )
		return false;

	BOOL bAxInit = AtlAxWinInit();
	if ( !bAxInit )
		return false;

	hr = _Module.Init(NULL, ::GetModuleHandle(0), &LIBID_MSHTML);
	if ( FAILED(hr) )
		return false;

	m_hWndMain = hWndMain;
	WNDCLASSEX wcex = {0};
	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= DefWindowProc;	
	wcex.hInstance		= ::GetModuleHandle(0);
	wcex.lpszClassName	= HOST_PAGE_CLASS;
	RegisterClassEx(&wcex);

	CRect rctMainClient;
	::GetWindowRect(hWndMain, &rctMainClient);
	m_hWndWebPageParent = ::CreateWindowW(HOST_PAGE_CLASS, NULL, WS_CHILD|WS_VISIBLE, 
		0, 20, rctMainClient.right, rctMainClient.bottom, 
		hWndMain, NULL, wcex.hInstance, NULL);

	m_pTabs = CTabHost::GetTabHostInstance(hWndMain);	
	m_pTabs->SetTabActionWacther(this);
	return true;
}

bool CWebPageManager::ActivateWebPage(PAGE_ID id)
{
	int curActiveId = m_pTabs->GetActivateTab();
	if ( id == curActiveId )
		return true;

	m_webpages[curActiveId].pPage->ShowWebPage(false);
	m_webpages[id].pPage->ShowWebPage(true);
	m_pTabs->ActivateTab(id);
	return true;
}

CWebPage* CWebPageManager::NewWebPage(PAGE_ID id, LPCTSTR pszUrl)
{
	CWebPage *pNewWebPage = new CWebPage();
	if ( !pNewWebPage->CreateWebBrowser(m_hWndWebPageParent, id, NULL) )
	{
		delete pNewWebPage;
		return NULL;
	}

	if ( pszUrl != NULL )
		pNewWebPage->Navigate(pszUrl);

	SWebPageInfo info = {0};
	info.pPage = pNewWebPage;
	info.pBrowserSink = new CBrowserEventSink();
	info.pHtmlWinSink = new CHtmlWindowEventSink();

	CComQIPtr<IWebBrowser2> spWeb(pNewWebPage->GetWebDisptch());
	info.pBrowserSink->Connect(this, spWeb);
	
	m_webpages[id] = info;
	m_order.push_back(id);
	m_pTabs->PushNewTab(id);
	m_pTabs->ActivateTab(id);
	return pNewWebPage;
}


bool CWebPageManager::CloseWebPage(PAGE_ID id)
{	
	m_webpages[id].pBrowserSink->Disconnect(this);
	m_webpages[id].pHtmlWinSink->Disconnect(this);
	m_webpages[id].pPage->CloseWebBrowser();	
	
	delete m_webpages[id].pPage;
	delete m_webpages[id].pBrowserSink;
	delete m_webpages[id].pHtmlWinSink;

	m_webpages.erase(id);
	m_pTabs->RemoveTab(id);
	return true;
}

int CWebPageManager::FindIdByBrowserSink(IDispatch *pBrowserSink)
{
	CBrowserEventSink *pSink = dynamic_cast<CBrowserEventSink *>(pBrowserSink);
	if ( pSink == NULL )
		return 0;

	WEBPAGES_INFO &all = m_webpages;
	WEBPAGES_INFO_ITER it;
	int idFind = 0;

	for ( it = all.begin(); it != all.end(); ++it )
	{
		const SWebPageInfo &info = it->second;
		if ( info.pBrowserSink == pSink )
		{
			idFind = it->first;
			break;
		}
	}

	return idFind;
}

int CWebPageManager::FindIdByHtmlWinSink(IDispatch *pHtmlWinSink)
{
	CHtmlWindowEventSink *pSink = dynamic_cast<CHtmlWindowEventSink *>(pHtmlWinSink);
	if ( pSink == NULL )
		return 0;

	WEBPAGES_INFO &all = m_webpages;
	WEBPAGES_INFO_ITER it;
	int idFind = 0;
	
	for ( it = all.begin(); it != all.end(); ++it )
	{
		const SWebPageInfo &info = it->second;
		if ( info.pHtmlWinSink == pSink )
		{
			idFind = it->first;
			break;
		}
	}

	return idFind;
}

int CWebPageManager::FindIdByWebPage(CWebPage *pPage)
{
	WEBPAGES_INFO &all = m_webpages;
	WEBPAGES_INFO_ITER it;
	int idFind = 0;
	
	for ( it = all.begin(); it != all.end(); ++it )
	{
		const SWebPageInfo &info = it->second;
		if ( info.pPage == pPage )
		{
			idFind = it->first;
			break;
		}
	}

	return idFind;
}


void CWebPageManager::RecalcLayout()
{
	CRect rctClient;
	::GetClientRect(m_hWndMain, &rctClient);

	CPoint ptWebPage = rctClient.TopLeft();
	CSize szWebPage = rctClient.Size();
	
	if ( m_pTabs != NULL )
	{
		CRect rctTabs = m_pTabs->GetTabHostPosSize();
		CSize szTabs(rctClient.right, rctTabs.Height());
		
		ptWebPage.y = szTabs.cy;
		szWebPage.cy -= szTabs.cy;
		m_pTabs->ResizeTabHost(szTabs, NULL);
	}

	::SetWindowPos(m_hWndWebPageParent, NULL, ptWebPage.x, ptWebPage.y, szWebPage.cx, szWebPage.cy, SWP_NOACTIVATE);
	CRect rctWebParentClient;
	GetClientRect(m_hWndWebPageParent, &rctWebParentClient);

	WEBPAGES_INFO &all = m_webpages;
	WEBPAGES_INFO_ITER it;
	for ( it = all.begin(); it != all.end(); it++ )
	{
		it->second.pPage->ResizeWebPage(rctWebParentClient.Size(), rctWebParentClient.TopLeft());
	}
}


//
//----------------------------------------------------------------------------
// vitrual function from base class
//----------------------------------------------------------------------------
//
void CWebPageManager::OnTitleChange(IDispatch *pSinkThis, BSTR title)
{
	int id = FindIdByBrowserSink(pSinkThis);
	if ( id != 0 )
	{
		m_webpages[id].pPage->SetTitle(title);
	}
}

void CWebPageManager::OnPreNavigate(IDispatch *pSinkThis)
{	
}

void CWebPageManager::OnDocumentComplete(IDispatch *pSinkThis, IDispatch *pWebBrowser2, BSTR pszUrl)
{
	LPCTSTR psz = pszUrl;

	int id = FindIdByBrowserSink(pSinkThis);
	if ( id != 0 && pWebBrowser2 == m_webpages[id].pPage->GetWebDisptch() )
	{
		m_webpages[id].pPage->OnDocumentComplete();

		CComPtr<IHTMLWindow2> spHtmlWin;
		spHtmlWin = m_webpages[id].pPage->GetHtmlWindow();

		if ( spHtmlWin != NULL )
			m_webpages[id].pHtmlWinSink->Connect(this, spHtmlWin);
	}
}

void CWebPageManager::OnOtherEvent(IDispatch *pSinkThis, DISPID dispIdMember, DISPPARAMS *pDispParams, VARIANT *pVarResult)
{
	if ( dispIdMember == DISPID_NEWWINDOW2 )
	{
		int id = GetNewId();
		CWebPage* page = NewWebPage(id, NULL);		
		*pDispParams->rgvarg[0].pboolVal = FALSE;
		*pDispParams->rgvarg[1].ppdispVal = page->GetWebDisptch();		

		int idCur = FindIdByBrowserSink(pSinkThis);
		m_webpages[idCur].pPage->ShowWebPage(false);
	}
}

void CWebPageManager::OnHtmlWndScroll(IDispatch *pSinkThis)
{
}



void CWebPageManager::OnTabClick(int id)
{
	ActivateWebPage(id);
}

void CWebPageManager::OnTabDblClick(int id)
{
	if ( MessageBox(m_hWndMain, L"Are you sure to close this page?", L"Warning", MB_YESNO) == IDYES )
		CloseWebPage(id);	
}

void CWebPageManager::OnTabClose(int id)
{
}

void CWebPageManager::OnTabHide(int id)
{
}
